package com.sl.au.controller;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.sl.au.entity.Account;
import com.sl.au.entity.DateQueryItem;
import com.sl.au.entity.DoubleQueryItem;
import com.sl.au.entity.IntegerQueryItem;
import com.sl.au.entity.M2R;
import com.sl.au.entity.Module;
import com.sl.au.entity.NumQueryItem;
import com.sl.au.entity.User;
import com.sl.au.service.AccountService;
import com.sl.au.service.M2RService;
import com.sl.au.service.ModuleService;
import com.sl.utils.DataConverter;

import net.coobird.thumbnailator.Thumbnails;

public class BaseController implements ErrorController {

	private static final String PATH = "/error";
	protected static Module module = null;
	@Value("${web.upload-path}")
	protected String fileUploadPath;

	public String getFileUploadPath() {
		return fileUploadPath;
	}

	public void setFileUploadPath(String fileUploadPath) {
		this.fileUploadPath = fileUploadPath;
	}

	// 移动端访问带的固定参数
	protected final String DEVICE = "mobile";
	// 移动端访问带的参数
	private String identify;

	public String getIdentify() {
		return identify;
	}

	@Autowired
	HttpServletRequest request;

	@Autowired
	M2RService m2rService;
	@Autowired
	ModuleService moduleService;
	@Autowired
	AccountService accountService;

	public ModelAndView createLayoutView(String rightViewName) {
		ModelAndView mv = new ModelAndView("layout/layout");
		mv.addObject("rightViewName", rightViewName);
		mv.addObject("canReadCustomer", this.canReadCustomer());
		return mv;
	}

	public ModelAndView createSingleView(String rightViewName) {
		ModelAndView mv = new ModelAndView(rightViewName);
		return mv;
	}

	/**
	 * 
	 * @param where
	 *            传到磁盘的那个位置
	 * @param type
	 *            上传的目录类型构建,比如巡检类图片
	 * @param file
	 * @return
	 * @throws IOException
	 */
	public String getUploadFilePath(String where, String type, MultipartFile file) {
		/*SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
		String datePath = sdf.format(new Date());*/

		String path = where + type ;//+ "/" + datePath;
		File dir = new File(path);// c:/upload/img/inspection/20180203020255
		if (!dir.exists()) {
			dir.mkdirs();
		}

		// 获取文件的名称
		String fileName =file.getOriginalFilename();
		if(fileName.contains("/")){
			String[] sp=fileName.split("/");
			fileName= sp[sp.length-1];	
		}

		InputStream in = null;
		FileOutputStream fos = null;
		path += "/" + (UUID.randomUUID().toString() + fileName);// c:/upload/img/inspection/20180203020255/....png
		try {
			// 获取文件的输入流
			in = file.getInputStream();
			// 将文件写入到磁盘中

			fos = new FileOutputStream(path);
			FileCopyUtils.copy(in, fos);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (fos != null) {
					fos.close();
					fos = null;
				}
				if (in != null) {
					in.close();
					in = null;
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
			try{
				commpressPicForScale(path,path,300, 0.8);
			}catch (Exception e){
				e.printStackTrace();
			}
		}
		path = path.substring(where.length());
		return path;
	}
	
	
	/** 
     * 根据指定大小和指定精度压缩图片 
     *  
     * @param srcPath 
     *            源图片地址 
     * @param desPath 
     *            目标图片地址 
     * @param desFilesize 
     *            指定图片大小，单位kb 
     * @param accuracy 
     *            精度，递归压缩的比率，建议小于0.9 
     * @return 
     */  
    public String commpressPicForScale(String srcPath, String desPath,  
            long desFileSize, double accuracy) {  
        if (StringUtils.isEmpty(srcPath) || StringUtils.isEmpty(srcPath)) {  
            return null;  
        }  
        if (!new File(srcPath).exists()) {  
            return null;  
        }  
        try {  
            File srcFile = new File(srcPath);  
            long srcFileSize = srcFile.length();  
//          System.out.println("源图片：" + srcPath + "，大小：" + srcFileSize / 1024 + "kb");  
  
            // 1、先转换成jpg  
            Thumbnails.of(srcPath).scale(1f).toFile(desPath);  
            // 递归压缩，直到目标文件大小小于desFileSize  
            commpressPicCycle(desPath, desFileSize, accuracy);  
  
            File desFile = new File(desPath);  
//          System.out.println("目标图片：" + desPath + "，大小" + desFile.length() / 1024 + "kb");  
//          System.out.println("图片压缩完成！");  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
        return desPath;  
    }
  
    private void commpressPicCycle(String desPath, long desFileSize,  
            double accuracy) throws IOException {  
        File srcFileJPG = new File(desPath);  
        long srcFileSizeJPG = srcFileJPG.length();  
        // 2、判断大小，如果小于500kb，不压缩；如果大于等于500kb，压缩  
        if (srcFileSizeJPG <= desFileSize * 1024) {  
            return;  
        }  
        // 计算宽高  
        BufferedImage bim = ImageIO.read(srcFileJPG);  
        int srcWdith = bim.getWidth();  
        int srcHeigth = bim.getHeight();  
        int desWidth = new BigDecimal(srcWdith).multiply(  
                new BigDecimal(accuracy)).intValue();  
        int desHeight = new BigDecimal(srcHeigth).multiply(  
                new BigDecimal(accuracy)).intValue();  
  
        Thumbnails.of(desPath).size(desWidth, desHeight)  
                .outputQuality(accuracy).toFile(desPath);  
        commpressPicCycle(desPath, desFileSize, accuracy);  
    }

	/**
	 * 得到当前登录用户账号
	 * 
	 * @return
	 */
	// @Cacheable("account")
	protected Account getMyAccount() {
		Account a = null;
		String crmout = request.getHeader("crm-out");
		String outkey = "D9A61EBF-4CC6-4E49-9561-58A6E34F34DF";
		String userid = request.getHeader("userid");
		if (StringUtils.hasText(crmout) && crmout.equals(outkey) && StringUtils.hasText(userid)) {

			// CRM外部调用
			a = new Account();
			User user = new User();
			user.setId(userid);
			a.setUser(user);

		} else if (this.isMobile()) {
			String accountId = request.getHeader("accountid");
			if (StringUtils.hasText(accountId)) {
				a = accountService.getRepository().getOne(accountId);
			}
		} else
			a = (Account) request.getSession().getAttribute("account");

		return a;
	}

	/**
	 * 在当前SESSION中存储变量
	 * 
	 * @param variableName
	 * @param value
	 */
	protected <T> void addSession(String variableName, T value) {
		request.getSession().setAttribute(variableName, value);
	}

	/**
	 * 从当前SESSION中读取变量
	 * 
	 * @param variableName
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected <T> T getSession(String variableName) {
		T r = null;
		r = (T) request.getSession().getAttribute(variableName);
		return r;
	}

	protected Module getPageModule(String moduleName) {
		Module m = null;
		m = moduleService.getRepository().findByName(moduleName);
		if (null == m)
			return null;
		if (null == this.getMyAccount())
			return null;
		String roleId = this.getMyAccount().getRole().getId();
		M2R m2r = this.m2rService.getRepository().findByRoleIdAndModuleId(roleId, m.getId());
		if (m2r != null) {
			m.setCanAdd(m2r.isAddOnly());
			m.setCanDelete(m2r.isDeleteOnly());
			m.setCanModify(m2r.isModifyOnly());
			m.setCanRead(m2r.isReadOnly());
			m.setCanOther1(m2r.isOther1Only());
			m.setCanOther2(m2r.isOther2Only());
			m.setDataFilter(m2r.getDataFilter());
		}
		return m;
	}

	protected Boolean isMobile() {
		String device = request.getHeader("device");
		return StringUtils.hasText(device) ? device.equals("mobile") : false;
	}

	@RequestMapping(value = PATH)
	public String error() {
		return "出错了";
	}

	@Override
	public String getErrorPath() {
		return PATH;
	}

	protected DateQueryItem getDateQueryItem(String propName) {
		String start = request.getParameter(propName + "StartDate");
		String end = request.getParameter(propName + "EndDate");
		DateQueryItem d = null;
		if (StringUtils.hasText(start)) {
			d = new DateQueryItem();
			d.setStartDate(DataConverter.formatDateYMD(start));
		}
		if (StringUtils.hasText(end)) {
			if (d == null)
				d = new DateQueryItem();
			d.setEndDate(DataConverter.formatDateYMD(end));
		}
		if (null != d) {
			d.setPropertyName(propName);
		}
		return d;
	}

	protected NumQueryItem getNumQueryItem(String propName) {
		String start = request.getParameter(propName + "StartNum");
		String end = request.getParameter(propName + "EndNum");
		NumQueryItem n = new NumQueryItem();
		if (StringUtils.hasText(start)) {
			n.setStartNum(Float.parseFloat(start));
		} else {
			n.setStartNum(0);
		}
		if (StringUtils.hasText(end)) {
			n.setEndNum(Float.parseFloat(end));
		} else {
			n.setEndNum(0);
		}
		if (null != n) {
			n.setPropertyName(propName);
		}
		return n;
	}

	protected IntegerQueryItem getIntegerQueryItem(String propName) {
		String start = request.getParameter(propName + "StartNum");
		String end = request.getParameter(propName + "EndNum");
		IntegerQueryItem n = null;
		if (StringUtils.hasText(start)) {
			n = new IntegerQueryItem();
			n.setStartNum(Integer.parseInt(start));
		} else {
			n = new IntegerQueryItem();
			n.setStartNum(0);
		}
		if (StringUtils.hasText(end)) {
			n.setEndNum(Integer.parseInt(end));
		} else {
			n.setEndNum(0);
		}
		if (null != n) {
			n.setPropertyName(propName);
		}
		return n;
	}

	protected DoubleQueryItem getDoubleQueryItem(String propName) {
		String start = request.getParameter(propName + "StartNum");
		String end = request.getParameter(propName + "EndNum");
		DoubleQueryItem n = null;
		if (StringUtils.hasText(start)) {
			n = new DoubleQueryItem();
			n.setStartNum(Double.parseDouble(start));
		} else {
			n = new DoubleQueryItem();
			n.setStartNum(0.0);
		}
		if (StringUtils.hasText(end)) {
			n.setEndNum(Double.parseDouble(end));
		} else {
			n.setEndNum(0.0);
		}
		if (null != n) {
			n.setPropertyName(propName);
		}
		return n;
	}

	protected Boolean canReadCustomer() {
		Boolean r = false;
		List<Module> modules = this.getMyAccount().getRole().getModules();
		for (Module m : modules) {
			if (m.getTarget().contains("/customer")) {
				r = true;
			}
		}
		return r;
	}

}
